/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */

import type { GraphCommit, RevisionTag } from "../core/index.js";

/**
 * Encapsulates a state machine that can be used by a {@link SharedTreeCore} manage resubmit phases,
 * especially dealing with the proper updating of enrichments on resubmitted commits.
 */
export interface ResubmitMachine<TChange> {
	/**
	 * @param revision - the revision of the commit that should be enriched
	 * @param getLocalCommitsSince - the local commits on this branch from oldest to newest, starting with the `revision`.
	 * @returns a version of the commit with updated enrichment, or undefined if this revision does not need to be resubmitted.
	 * A revision does not need to be resubmitted if it has already been sequenced, which can happen if it was also submitted by another client.
	 * Two clients can submit the same revision by both merging from the same shared branch.
	 */
	getEnrichedCommit(
		revision: RevisionTag,
		getLocalCommitsSince: () => readonly GraphCommit<TChange>[],
	): GraphCommit<TChange> | undefined;

	/**
	 * Must be when a commit is submitted or resubmitted.
	 * @param commit - the (enriched) commit (re)submitted. Not mutated.
	 */
	onCommitSubmitted(commit: GraphCommit<TChange>): void;

	/**
	 * Must be called on a commit after rollback, so it can be removed
	 * as it will never be (re)submitted.
	 * @param commit - The commit that was rolled back
	 */
	onCommitRollback(commit: GraphCommit<TChange>): void;

	/**
	 * Must be called after a sequenced commit is applied.
	 * Note that this may be called multiples times in a row after a number of sequenced commits have been applied
	 * (as opposed to always being called before the next sequenced commit is applied).
	 * @param revision - the revision of the sequenced commit.
	 * @param isLocal - whether the sequenced commit was generated by the local session.
	 */
	onSequencedCommitApplied(revision: RevisionTag, isLocal: boolean): void;
}
